package com.wujunshen.thread.atomicreference;

import java.util.concurrent.atomic.AtomicReference;
import lombok.AccessLevel;
import lombok.AllArgsConstructor;

/**
 * @author frank woo(吴峻申) <br>
 *     email:<a href="mailto:frank_wjs@hotmail.com">frank_wjs@hotmail.com</a> <br>
 * @date 2020/7/18 11:31<br>
 */
public class LinkedStack<T> {
  private final AtomicReference<Node<T>> stacks = new AtomicReference<>();

  public T push(T e) {
    Node<T> oldNode;
    Node<T> newNode;
    // 这里的处理非常的特别，也是必须如此的。
    while (true) {
      oldNode = stacks.get();
      newNode = new Node<>(e, oldNode);
      if (stacks.compareAndSet(oldNode, newNode)) {
        return e;
      }
    }
  }

  public T pop() {
    Node<T> oldNode;
    Node<T> newNode;
    while (true) {
      oldNode = stacks.get();
      newNode = oldNode.next;
      if (stacks.compareAndSet(oldNode, newNode)) {
        return oldNode.object;
      }
    }
  }

  @AllArgsConstructor(access = AccessLevel.PRIVATE)
  private static final class Node<T> {
    private final T object;
    private final Node<T> next;
  }
}
